home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Frameworks / Hsoi's App Shell 1.0a4 / Hsoi's App Shell Source / HASScripting.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-28  |  10.2 KB  |  395 lines  |  [TEXT/CWIE]

  1. /*
  2.     HASScripting.c from Hsoi's App Shell ©1995-1997 John C. Daub.  All rights reserved.
  3.     
  4.     Minimal Scripting Support:
  5.     service "get data" and "set data" events
  6.     in which the object descriptor is "contents of selection"
  7.     
  8.     This file (as is) is taken from WEDemoScripting.c from the WASTE Demo App written
  9.     by Marco Piovanelli.  Slight modifications have been made for the code to work (and
  10.     be consistent with) Hsoi's App Shell.
  11.     
  12.     Based on public domain code written by:
  13.     Ed Lai, Apple Computer Inc.
  14.     
  15.     Copyright © 1993-1995 Marco Piovanelli
  16.     All Rights Reserved
  17.  
  18. */
  19.  
  20.  
  21. /*    How to use this and/or test things:
  22.  
  23.     With this basic and minimal scripting support that HAS has, here's how you
  24.     can see it in action.
  25.     
  26.     First, you must have some way of implimenting the script, such as Apple's
  27.     Script Editor.
  28.     
  29.     Launch the Script Editor and in the editing window, type something like
  30.     this:
  31.     
  32.     [to try get data]
  33.     
  34.     get the contents of selection of application "Hsoi's App Shell Demo 68k"
  35.     
  36.     [to try set data]
  37.     
  38.     set the contents of selection of application "Hsoi's App Shell Demo 68k" to "fred"
  39.  
  40.     (you can substitute the name of your application in place of Hsoi's App Shell Demo 68k,
  41.     but whatever you do, make sure it's the exact name of the application)
  42.     
  43.     then, launch the HAS Demo.  Type something, select it (or part of it).  Switch back
  44.     to the Script Editor (and you might want to position windows on your monitor
  45.     so that you can see both the Script Editor result window and the HAS window with
  46.     your selection) and run the script.  You should see things work just peachy.
  47.  
  48.  
  49. */
  50.  
  51. #pragma mark ••• #includes •••
  52.  
  53. #ifndef __AEOBJECTS__
  54. #include <AEObjects.h>
  55. #endif
  56.  
  57. #ifndef __AEREGISTRY__
  58. #include <AERegistry.h>
  59. #endif
  60.  
  61. #ifndef _WASTE_
  62. #include "WASTE.h"
  63. #endif
  64. #include "HASGlobals.h"
  65. #ifndef __HSOIS_APP_SHELL__
  66. #include "HASMain.h"
  67. #endif
  68. #include "HASScripting.h"
  69. #include "HASUtilities.h"
  70.  
  71. #pragma mark -
  72. #pragma mark ••• Utils •••
  73.  
  74. // initialize a descriptor
  75.  
  76. static void    HsoiInitDesc(AEDesc *desc)
  77. {
  78.     desc->descriptorType = typeNull;
  79.     desc->dataHandle = NULL;
  80.     
  81.     return;
  82. }
  83.  
  84. static Boolean HsoiPropertyOf(const AERecord *spec, short *propLevel, PropArray properties)
  85. {
  86.     AERecord objSpec;
  87.     AEKeyword key;
  88.     DescType theType;
  89.     DescType actualType;
  90.     Size actualSize;
  91.     Boolean retVal = false;
  92.     
  93.     HsoiInitDesc(&objSpec);
  94.     
  95.     // if spec is an Apple event (*propLevel = 0), extract its direct parameter
  96.     // otherwise spec is an object specifier record: extract its container param
  97.     key = (*propLevel == 0) ? keyDirectObject : keyAEContainer;
  98.     
  99.     // extract object specifier
  100.     if (AEGetParamDesc(spec, key, typeAERecord, &objSpec) != noErr)
  101.         goto cleanup;
  102.     
  103.     // does this object specifier specify a property?
  104.     if (AEGetParamPtr(&objSpec, keyAEDesiredClass, typeType, &actualType,
  105.                     &theType, sizeof(theType), &actualSize) != noErr)
  106.         goto cleanup;
  107.     
  108.     // sanity check: make sure the key form is formPropertyID
  109.     // this is probably redundant, but checking doesn't hurt
  110.     if (AEGetParamPtr(&objSpec, keyAEKeyForm, typeEnumerated, &actualType,
  111.                     &theType, sizeof(theType), &actualSize) != noErr)
  112.         goto cleanup;
  113.     if (theType != formPropertyID)
  114.         goto cleanup;
  115.     
  116.     // which property does this object specifier specify?
  117.     if (AEGetParamPtr(&objSpec, keyAEKeyData, typeType, &actualType,
  118.                     &theType, sizeof(theType), &actualSize) != noErr)
  119.         goto cleanup;
  120.     
  121.     // bump property level and save property tag into property array
  122.     properties[(*propLevel)++] = theType;
  123.     
  124.     // property of what?
  125.     if (AESizeOfParam(&objSpec, keyAEContainer, &actualType, &actualSize) == noErr)
  126.         if (actualType == typeNull)
  127.             // property of application (i.e., null container): we are done
  128.             retVal = true;
  129.         else if ((actualType == typeObjectSpecifier) && (*propLevel < kMaxPropLevel))
  130.             // property of another object, so do a recursive call
  131.             // unless we have already reached max recursion depth
  132.             retVal = HsoiPropertyOf(&objSpec, propLevel, properties);
  133.  
  134. cleanup:
  135.     AEDisposeDesc(&objSpec);
  136.     return retVal;
  137. }
  138.  
  139. #pragma mark -
  140. #pragma mark ••• Event Handler Utils •••
  141.  
  142. OSErr    HsoiWEGetContentsDesc(long rangeStart, long rangeEnd, Boolean wantStyledText,
  143.         AEDesc *desc, WEReference we)
  144. {
  145.     AEDesc textDesc, stylesDesc, recordDesc;
  146.     OSErr err;
  147.  
  148.     HsoiInitDesc(desc);
  149.     HsoiInitDesc(&textDesc);
  150.     HsoiInitDesc(&stylesDesc);
  151.     HsoiInitDesc(&recordDesc);
  152.     
  153.     // allocate a handle to hold the text
  154.     textDesc.dataHandle = NewHandle(0);
  155.     textDesc.descriptorType = typeChar;
  156.     if ((err = MemError()) != noErr)
  157.         goto cleanup;
  158.     
  159.     if (wantStyledText)
  160.     {
  161.         // allocate a handle to hold the styles
  162.         stylesDesc.dataHandle = NewHandle(0);
  163.         stylesDesc.descriptorType = typeScrapStyles;
  164.         if ((err = MemError()) != noErr)
  165.             goto cleanup;
  166.     } // if wantStyledText
  167.     
  168.     // make a copy of the specified text range
  169.     if ((err = WECopyRange(rangeStart, rangeEnd, textDesc.dataHandle,
  170.             (StScrpHandle) stylesDesc.dataHandle, NULL, we)) != noErr)
  171.         goto cleanup;
  172.     
  173.     if (wantStyledText)
  174.     {
  175.         // create an Apple event record to hold text + styles
  176.         if ((err = AECreateList(NULL, 0, true, &recordDesc)) != noErr)
  177.             goto cleanup;
  178.         
  179.         // add the text descriptor to the record
  180.         if ((err = AEPutParamDesc(&recordDesc, keyAEText, &textDesc)) != noErr)
  181.             goto cleanup;
  182.         AEDisposeDesc(&textDesc);
  183.         
  184.         // add the styles descriptor to the record
  185.         if ((err = AEPutParamDesc(&recordDesc, keyAEStyles, &stylesDesc)) != noErr)
  186.             goto cleanup;
  187.         AEDisposeDesc(&stylesDesc);
  188.         
  189.         // coerce the record into a styled text descriptor
  190.         if ((err = AECoerceDesc(&recordDesc, typeStyledText, desc)) != noErr)
  191.             goto cleanup;
  192.  
  193.     }
  194.     else {
  195.         *desc = textDesc;
  196.         HsoiInitDesc(&textDesc);
  197.     }
  198.  
  199.     err = noErr;
  200.  
  201. cleanup:
  202.     AEDisposeDesc(&textDesc);
  203.     AEDisposeDesc(&stylesDesc);
  204.     AEDisposeDesc(&recordDesc);
  205.     
  206.     return err;
  207. }
  208.  
  209. OSErr    HsoiWESetContentsDesc(long rangeStart, long rangeEnd,
  210.                 const AEDesc *desc, WEReference we)
  211. {
  212.     AEDesc textDesc, stylesDesc, recordDesc;
  213.     OSErr err;
  214.     
  215.     HsoiInitDesc(&textDesc);
  216.     HsoiInitDesc(&stylesDesc);
  217.     HsoiInitDesc(&recordDesc);
  218.  
  219.     // we expect desc type to be either TEXT or STXT
  220.     if (desc->descriptorType == typeStyledText)
  221.     {
  222.         // STYLED TEXT
  223.         // coerce the styled text descriptor to an Apple event record
  224.         if ((err = AECoerceDesc(desc, typeAERecord, &recordDesc)) != noErr)
  225.             goto cleanup;
  226.         
  227.         // extract text + styles from the record
  228.         if ((err = AEGetParamDesc(&recordDesc, keyAEText, typeChar, &textDesc)) != noErr)
  229.             goto cleanup;
  230.         if ((err = AEGetParamDesc(&recordDesc, keyAEStyles, typeScrapStyles, &stylesDesc)) != noErr)
  231.             goto cleanup;
  232.     }
  233.     else {
  234.         // UNSTYLED TEXT
  235.         if ((err = AECoerceDesc(desc, typeChar, &textDesc)) != noErr)
  236.             goto cleanup;
  237.     }
  238.     
  239.     // replace the specified range with the given text
  240.     HLock(textDesc.dataHandle);
  241.     WESetSelection(rangeStart, rangeEnd, we);
  242.     err = WEInsert(*textDesc.dataHandle, GetHandleSize(textDesc.dataHandle),
  243.                 (StScrpHandle) stylesDesc.dataHandle, NULL, we);
  244.     HUnlock(textDesc.dataHandle);
  245.  
  246. cleanup:
  247.     AEDisposeDesc(&recordDesc);
  248.     AEDisposeDesc(&textDesc);
  249.     AEDisposeDesc(&stylesDesc);
  250.     
  251.     return err;
  252. }
  253.  
  254. #pragma mark -
  255. #pragma mark ••• Event Handlers •••
  256.  
  257. static pascal OSErr HsoiHandleGetData(const AppleEvent *ae, AppleEvent *reply, long refCon)
  258. {
  259. #pragma unused (refCon)
  260.  
  261.     AEDesc textDesc;
  262.     DocumentHandle hDocument;
  263.     short propLevel = 0;
  264.     PropArray properties;
  265.     FlavorType requestedType;
  266.     Boolean wantStyledText = false;
  267.     DescType actualType;
  268.     Size actualSize;
  269.     long selStart, selEnd;
  270.     OSErr err;
  271.  
  272.     HsoiInitDesc(&textDesc);
  273.     
  274.     // the only Apple event object we recognize is "contents of selection"
  275.     err = errAENoSuchObject;
  276.     if (!HsoiPropertyOf(ae, &propLevel, properties) || (propLevel != 2) ||
  277.         (properties[0] != pContents) || (properties[1] != pSelection))
  278.     {
  279.         goto cleanup;
  280.     }
  281.     
  282.     // extract the optional parameter keyAERequestedType, if present
  283.     // The Apple Event Registry says this parameter can be a list
  284.     // of type tags, but in most cases it is just a single tag, as we assume here.
  285.     if (AEGetParamPtr(ae, keyAERequestedType, typeType, &actualType,
  286.         &requestedType, sizeof(requestedType), &actualSize) == noErr)
  287.     {
  288.         wantStyledText = (requestedType == typeStyledText);
  289.     }
  290.     
  291.     // make sure there is a document window in front
  292.     err = errAENoUserSelection;
  293.     if ((hDocument = HsoiGetWindowDocument(FrontWindow())) == NULL)
  294.     {
  295.         goto cleanup;
  296.     }
  297.     
  298.     // get the selection range
  299.     WEGetSelection(&selStart, &selEnd, (*hDocument)->we);
  300.     
  301.     // create an Apple event descriptor for the selected text
  302.     if ((err = HsoiWEGetContentsDesc(selStart, selEnd, wantStyledText,
  303.                 &textDesc, (*hDocument)->we)) != noErr)
  304.     {
  305.         goto cleanup;
  306.     }
  307.     
  308.     // put the text descriptor into the reply event
  309.     if ((err = AEPutParamDesc(reply, keyDirectObject, &textDesc)) != noErr)
  310.     {
  311.         goto cleanup;
  312.     }
  313.  
  314.     // clear result code
  315.     err = noErr;
  316.  
  317. cleanup:
  318.     AEDisposeDesc(&textDesc);
  319.  
  320.     return err;
  321. }
  322.  
  323. static pascal OSErr HsoiHandleSetData(const AppleEvent *ae, AppleEvent *reply, long refCon)
  324. {
  325. #pragma unused (reply, refCon)
  326.  
  327.     AEDesc textDesc;
  328.     DocumentHandle hDocument;
  329.     short propLevel = 0;
  330.     PropArray properties;
  331.     long selStart, selEnd;
  332.     OSErr err;
  333.     
  334.     HsoiInitDesc(&textDesc);
  335.  
  336.     // the only Apple event object we recognize is "contents of selection"
  337.     err = errAENoSuchObject;
  338.     if (!HsoiPropertyOf(ae, &propLevel, properties) || (propLevel != 2) ||
  339.         (properties[0] != pContents) || (properties[1] != pSelection))
  340.     {
  341.         goto cleanup;
  342.     }
  343.     
  344.     // make sure there is a document window in front
  345.     err = errAENoUserSelection;
  346.     if ((hDocument = HsoiGetWindowDocument(FrontWindow())) == NULL)
  347.     {
  348.         goto cleanup;
  349.     }
  350.         
  351.     // extract the required keyAEData parameter
  352.     if ((err = AEGetParamDesc(ae, keyAEData, typeWildCard, &textDesc)) != noErr)
  353.         goto cleanup;
  354.     
  355.     // get current selection range
  356.     WEGetSelection(&selStart, &selEnd, (*hDocument)->we);
  357.     
  358.     // set the contents of the selection
  359.     if ((err = HsoiWESetContentsDesc(selStart, selEnd, &textDesc, (*hDocument)->we)) != noErr)
  360.     {
  361.         goto cleanup;
  362.     }
  363.     
  364.     // clear result code
  365.     err = noErr;
  366.  
  367. cleanup:
  368.     AEDisposeDesc(&textDesc);
  369.  
  370.     return err;
  371. }
  372.  
  373. #pragma mark -
  374. #pragma mark ••• Install Handlers •••
  375.  
  376. // the apple event installed...called in HsoiDoAEInstallation()
  377.  
  378. OSErr    HsoiInstallCoreHandlers(void)
  379. {
  380.     OSErr err;
  381.     
  382.     if ((err = AEInstallEventHandler(kAECoreSuite, kAEGetData,
  383.             NewAEEventHandlerProc(HsoiHandleGetData), 0L, false)) != noErr)
  384.     {
  385.         return err;
  386.     }
  387.     
  388.     if ((err = AEInstallEventHandler(kAECoreSuite, kAESetData,
  389.             NewAEEventHandlerProc(HsoiHandleSetData), 0L, false)) != noErr)
  390.     {
  391.         return err;
  392.     }
  393.     
  394.     return noErr;
  395. }